#include "LFSR.h"

/*Calcule le nouveau bit produit par un LFSR dont le polynôme de rétroaction est P (de degré <= 32),
 * et dont le registre contient actuellement a
 */
int retroaction(uint a, uint P)
{
  P = P<<1; 
  return uXOR(P & a);
}

uint registre(uint a, int d, int L)
/* a est une suite de 32 bits. Cette fonction renvoie, à l'envers, L bits de a, à partir du n°d.
 * Elle renvoie donc le contenu du registre d'un LFSR de longueur L <= 31,
 * qui a dans sa case de droite le bit n°d de a et dans sa case de gauche le bit n°(d+L-1)
 * 
 * ex :
 * 
 * a = 00010011100110000000000000000000
 * d = 3
 * L = 7
 *   ________________
 *  |      |   |     |
 *   -->|0|1|1|1|0|0|1|-->
 *       ^           ^
 *       |           |
 *       |           bit n°3 (d) de a
 *       bit n°9 (d+L-1 = 3+7-1) de a
 * 
 * La fonction renvoie alors : 01110010000000000000000000000000
 * 
 */
{
  uint r = 0;
  int i;
  for (i = 0; i < L; i++)
  {
    if (ubit(a, d + i) == 0) uzero(&r, L-1-i);
    else uun(&r, L-1-i);
  }
}


uint* LFSR(int L, uint P, uint a, int N)
/* Calcule les N premiers bits générés par un LFSR de longueur L et de polynôme de rétroaction P,
 * qui contient initialement les L premiers bits de a.
 */ 
{
  int nb = N / 32; //nombre de uint nécessaire pour stocker la suite générée
  
  uint* G = malloc(nb * sizeof(uint)); //La suite générée G sera un tableau de nb uints
  
  uint b = retourne(a, L);
  P = P << 1; //On n'a pas besoin du premier coefficient de P : c'est toujours 1 (1 + ...)
  
  int i;
  for (i = 0; i < N; i++) //Itérations du LFSR
  {
    if (uXOR(P & b) == 0) //Si le nouveau bit généré à gauche est 0
    {
      b = b >> 1; //On décale b d'un cran vers la droite
      uzero(&b, 0); //On place le nouveau bit généré à gauche
    }
    else //Si le bit généré est 1
    {
      b = b >> 1;
      uun(&b, 0);
    }
    
    if (ubit(b, L) == 0) uzero(G, i); //Le bit qui sort à droite du LFSR est placé dans G.
    else uun(G, i);
  } 
  return G;
}


main()
{
  int L = 5;
  uint P, a; 
  
  Nedit(&P, 1, "100110"); //polynome de retroaction
  Nedit(&a, 1, "100111"); //contenu du registre
  
  printf("P : ");
  Naffiche(&P, 1, 8);
  printf("\na : ");
  Naffiche(&a, 1, 8);
  printf("\n");
  
  uint crypte;  
  uint* G = LFSR(L, P, a, 32);
  
  Naffiche(G, 1, 32);
  printf("\n");
}
